package main

import (
	"strings"
    "fmt"
    "github.com/360EntSecGroup-Skylar/excelize"
    "os"
    "io/ioutil"
    "io"
    "encoding/json"
    "strconv"
    "path"
    "compress/gzip"
    "time"
    // "crypto/md5"
)
var rootData = make(map[string]interface{})
var glConfig = make(map[string]interface{})
var configPath string
var xlsxPath string
var openGzip bool
type GLConfig interface {
    
}
type BaseConfig interface {
    
}
//arguments 
//1 xlsx路径
//2 输出json路径和文件名
//3 是否打开gzip
func main() {
    xlsxPath = os.Args[1];
    configPath = os.Args[2];
    openGzip = os.Args[3] == "true";
    fmt.Println(xlsxPath + " "+ configPath)
    dealFileList(xlsxPath)
    fmt.Println("配置转换完成");
}

func dealFileList(xlsFolder string) {
    files, _ := ioutil.ReadDir(xlsFolder)
    for _, file := range files {
        if file.IsDir() {
            // listFile(myfolder + "/" + file.Name())
        } else if path.Ext(xlsxPath + string(os.PathSeparator)+file.Name()) == ".xlsx"{
            //查看md5变化
            // md5h := md5.New()
            // f,err := os.Open("xlsxPath + string(os.PathSeparator)+file.Name()")
            // if err!=nil{
            //     io.Copy(md5h, f)    
            //     fmt.Printf("md5 %x", md5h.Sum([]byte("")))
            // }
            fmt.Println(xlsFolder + string(os.PathSeparator) + file.Name())
            dealXlsx(xlsFolder + string(os.PathSeparator) + file.Name())
        }else{
            fmt.Println("skip:",xlsFolder + string(os.PathSeparator) + file.Name())
            writeERR("skip:" + xlsFolder + string(os.PathSeparator) + file.Name())
        }
    }
    
     //删除老配置
     os.Remove(configPath)
    //写入
    rootData["GLConfig"] = glConfig;
    bt, _ := json.Marshal(rootData)
    writeText(string(bt))

    // if openGzip{
    //     writeText(string(bt))
    // }else{
    //     writeText(string(bt))
    // }
}
func dealXlsx(xlsxName string){
    fmt.Println("parse xlsx:",xlsxName)
    xlsx, err := excelize.OpenFile(xlsxName)
    if err != nil {
        fmt.Println(err)
        return
    }
    sheets :=xlsx.GetSheetMap();
    // fmt.Println(sheets);
    for _,sheet:=range sheets{
        rows := xlsx.GetRows(sheet);
        // dealSheet(sheet,xlsx);
        fmt.Println("parse sheet:",sheet);
        exportType := xlsx.GetCellValue(sheet, "B1")
        //导出key
        exportKey := xlsx.GetCellValue(sheet, "B2")
        keyIndex := xlsx.GetCellValue(sheet, "B3")
        // if exportKey == ""{   //这么写有问题 会终止整个循环？？？？？？
        //     fmt.Println(xlsxName+" "+sheet+" export key empty  skiped");
        //     writeERR(xlsxName+" "+sheet+" export key empty  skiped");
        //     return
        // }
        if exportKey == ""{
            fmt.Println(xlsxName+" "+sheet+" export key empty  skiped");
            writeERR(xlsxName+" "+sheet+" export key empty  skiped");
        }else{
        //导出参数
        exportParam := xlsx.GetRows(sheet)[5];
        keys := rows[6]
        var values []string;
        if len(rows)>=8{
            values = rows[7]
        }
        if exportType == "map" {//转换成{'key':'value'}
            configDetail := make(map[string]interface{})
            shouldInsert := false
            allEmpty := true //标记是否全空
            for index,key:=range keys{

                if key != ""{
                    if values!=nil && index>0{
                        if checkParam(exportParam[index]){
                            val := values[index];
                            if(val!=""){
                                allEmpty = false;
                            }
                            newVal,err := strconv.Atoi(val)
                            if err==nil{
                                configDetail[key] = newVal
                            }else{
                                configDetail[key] = val
                            }
                         
                            shouldInsert = true;
                        }
                    }
                    
                }else{
                    // fmt.Println("舍弃空Key1");
                }
               
            }
            if shouldInsert &&!allEmpty{
                glConfig[exportKey] = configDetail
            }
            if allEmpty{
                fmt.Println(exportKey + "all empty & skipped")
                writeERR(exportKey + "all empty & skipped");
            }
        }else if keyIndex != ""{ //指定keyindex 转换成 ['key':{}]
            //这里需要处理两个key的情况 TODO: 改为多层key 使用下划线分割
            if(strings.Contains(keyIndex,"_")){
                fmt.Println(exportKey + "导出 ['key':{'key':'value'}] " )
                // configDetail := make(map[string]interface{})
                configDetail := make(map[string]map[string]interface{})
                kIdxs := strings.Split(keyIndex, "_")
                // kIdx,err := strconv.Atoi(keyIndex)
                kIdx,err1 := strconv.Atoi(kIdxs[0]);
                secKIdx,err2 := strconv.Atoi(kIdxs[1]);
                if err1!=nil{
                    fmt.Println(exportKey + "keys error1");
                }
                if err2!=nil{
                    fmt.Println(exportKey + "keys error2");
                }
                shouldInsert := false;
                
                for index,row:=range rows{
                    //第六行之后是数据
                    if index > 6{
                        configItem := make(map[string]interface{})
                        shouldItem := false;
                        allEmpty := true //标记是否全空

                        //遍历key
                        for idx,k:=range keys{
                            if k != ""{
                                //第一列为注释
                                if idx>0{
                                    if checkParam(exportParam[idx]){
                                        val :=  row[idx]
                                        if(val!=""){
                                            allEmpty = false;
                                        }
                                        newVal,err := strconv.Atoi(val)
                                        if err==nil{
                                            configItem[k] = newVal
                                        }else{
                                            configItem[k] = val
                                        }
                                        shouldItem = true;
                                        // configItem[k] = row[idx];
                                    }
                                }
                            }else{
                                // fmt.Println("舍弃空Key");
                            }
                            
                        }
                        if row[kIdx]!=""{
                            if shouldItem && !allEmpty{
                                if configDetail[row[kIdx]]== nil{
                                    configDetail[row[kIdx]] = make(map[string]interface{});
                                }
                                // bt,err := json.Marshal(configItem);
                                // if(err!=nil){
                                //     fmt.Println(err)
                                // }
                                // fmt.Println("add item "+ string(bt))
                                configDetail[row[kIdx]][row[secKIdx]] = configItem;
                                shouldInsert = true
                            }
                            if allEmpty{
                                fmt.Println(exportKey + "all empty & skipped")
                                writeERR(exportKey + "all empty & skipped");
                            }
                        }else{
                            // fmt.Println("舍弃空key")
                        }
                    }
    
                }
                if shouldInsert{
                    glConfig[exportKey] = configDetail
                }
               
            }else{
                configDetail := make(map[string]interface{})
                kIdx,err := strconv.Atoi(keyIndex)
                fmt.Println(exportKey + "导出 ['key':{}] " )
                shouldInsert := false;
                if err==nil{
                    for index,row:=range rows{
                        //第六行之后是数据
                        if index > 6{
                            configItem := make(map[string]interface{})
                            shouldItem := false;
                            allEmpty := true //标记是否全空

                            //便利key
                            for idx,k:=range keys{
                                if k != ""{
                                    //第一列为注释
                                    if idx>0{
                                        if checkParam(exportParam[idx]){
                                            val :=  row[idx]
                                            if(val!=""){
                                                allEmpty = false;
                                            }
                                            newVal,err := strconv.Atoi(val)
                                            if err==nil{
                                                configItem[k] = newVal
                                            }else{
                                                configItem[k] = val
                                            }
                                            // if val!=""{
                                            //     allEmpty = false;
                                            // }

                                            shouldItem = true;
                                            // configItem[k] = row[idx];
                                        }
                                    }
                                }else{
                                    // fmt.Println("舍弃空Key");
                                }
                             
                            }

                            if row[kIdx]!=""{
                                // if shouldItem&&!allEmpty{
                                if shouldItem &&!allEmpty{
                                    configDetail[row[kIdx]] = configItem;
                                    shouldInsert = true
                                }
                                if allEmpty{
                                    fmt.Println(exportKey + "all empty & skipped")
                                    writeERR(exportKey + "all empty & skipped");
                                }
                            }else{
                                // fmt.Println("舍弃空key")
                            }
                        }
        
                    }
                    if shouldInsert{
                        glConfig[exportKey] = configDetail
                    }
                }
            }

        } else { //转换成 [{'key','value'}]
            configDetail := make([]interface{},0)
            fmt.Println(exportKey + "导出 [{'key','value'}]")
            shouldInsert := false;
            for index,row:=range rows{
                //第六行之后是数据
                if index > 6{
                    configItem := make(map[string]interface{})
                    shouldItem := false;
                    allEmpty := true //标记是否全空

                    //便利key
                    for idx,k:=range keys{
                        if k != ""{
                            //第一列为注释
                            if idx>0{
                                if  checkParam(exportParam[idx]){
                                    val :=  row[idx]
                                    if(val!=""){
                                        allEmpty = false;
                                    }
                                    newVal,err := strconv.Atoi(val)
                                    if err==nil{
                                        configItem[k] = newVal
                                    }else{
                                        configItem[k] = val
                                    }
                                    // fmt.Println(configItem)
                                    shouldItem = true;
                                }
                            }
                           
                        }else{
                            // fmt.Println("舍弃空key")
                        }
                        
                    }
                    if shouldItem &&!allEmpty{
                        configDetail = append(configDetail,configItem)
                        shouldInsert = true
                    }
                    if allEmpty{
                        fmt.Println(exportKey + "all empty & skipped")
                        writeERR(exportKey + "all empty & skipped");
                    }
                }

            }
            if shouldInsert{
                glConfig[exportKey] = configDetail
            }
        }
        }

        
    }

}
//处理值 如果是数字 转成int
// func dealVal(txt string){
//     newVal,err := strconv.Atoi(txt)
//     if err==nil{
//         return newVal
//     }else{
//         return txt
//     }
// }
func checkParam(param string) bool {
    deal:= false;
    if(strings.Contains(param,"c")){
        deal = true;
    }
    return deal;
}

func writeText(txt string){
    var f *os.File
    var filename = configPath
    var err1 error
    if checkFileIsExist(filename) { //如果文件存在
		f, err1 = os.OpenFile(filename, os.O_RDWR, 0666) //打开文件
	} else {
		f, err1 = os.Create(filename) //创建文件
    }
    n, err1 := io.WriteString(f, txt)
    if err1!=nil {
        fmt.Println(n,err1)
    }
    //如果打开了gzip 自动压缩文件
    if openGzip {
        fmt.Println("Start CompressFile")
        err := CompressFile(filename+".min.json",filename);
        if err!=nil{
            fmt.Println("CompressFile failed",err)
        }else{
            fmt.Println("CompressFile success")
        }
    }else{
        fmt.Println("未开启GZIP")
    }
}
func writeERR(txt string){
    var f *os.File
    var filename = configPath+".err.txt"
    var err1 error
    if checkFileIsExist(filename) { //如果文件存在
		f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
	} else {
		f, err1 = os.Create(filename) //创建文件
    }
    currentTime:=time.Now()

    // n, err1 := io.WriteString(f, "\n"+txt+"|"+" \n");
    n,err1 := io.WriteString(f,ToString(txt,"|",currentTime,"\n"))
    
    if err1!=nil {
        fmt.Println(n,err1)
    }
}
func ToString(args ...interface{}) string {
    result := ""
    for _, arg := range args {
        switch val := arg.(type) {
            case int:
                result += strconv.Itoa(val)
            case string:
                result += val
        }
    }
    return result
}
func CompressFile(Dst string, Src string) error {
    newfile, err := os.Create(Dst)
    if err != nil {
        return err
    }
    defer newfile.Close()

    file, err := os.Open(Src)
    if err != nil {
        return err
    }

    zw := gzip.NewWriter(newfile)

    filestat, err := file.Stat()
    if err != nil {
        return nil
    }

    zw.Name = filestat.Name()
    zw.ModTime = filestat.ModTime()
    _, err = io.Copy(zw, file)
    if err != nil {
        return nil
    }

    zw.Flush()
    if err := zw.Close(); err != nil {
        return nil
    }
    return nil
}


func checkFileIsExist(filename string) bool {
	var exist = true
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		exist = false
	}
	return exist
}
